package org.fixed.dubboconsumer.service.impl;

import org.fixed.dubboconsumer.core.util.DubboCallUtil;
import org.fixed.dubboconsumer.core.util.JarUtils;
import org.fixed.dubboconsumer.entity.CallRequest;
import org.fixed.dubboconsumer.entity.InvokeVO;
import org.fixed.dubboconsumer.entity.MethodDTO;
import org.fixed.dubboconsumer.entity.ParamDTO;
import org.fixed.dubboconsumer.entity.ResourceDTO;
import org.fixed.dubboconsumer.entity.ResourceVO;
import org.fixed.dubboconsumer.service.ResourceService;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springside.modules.utils.mapper.JsonMapper;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import static org.fixed.dubboconsumer.core.util.ReflectionUtils.constactParamete;
import static org.fixed.dubboconsumer.core.util.ReflectionUtils.getMethod;

/**
 * 〈一句话功能简述>
 * ${DESCRIPTION}
 * Author:xuzhongwei
 * Date:2019/1/3
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 获取方法列表
     *
     * @param resourceVO
     * @return
     */
    @Override
    public ResourceDTO execute(ResourceVO resourceVO) throws Exception {
        //获取接口class
        Class clazz = JarUtils.getInterfaceClass(resourceVO);
        //获取接口全部方法
        Method[] methods = clazz.getMethods();

        ResourceDTO resourceDTO = new ResourceDTO();

        resourceDTO.setInterfaceName(resourceVO.getInterfaceName());

        if (ArrayUtils.isNotEmpty(methods)) {
            for (Method method : methods) {
                MethodDTO methodDTO = new MethodDTO();
                methodDTO.setMethodName(method.getName());
                resourceDTO.addMethod(methodDTO);

                Class<?>[] parameterTypes = method.getParameterTypes();
                if (ArrayUtils.isNotEmpty(parameterTypes)) {
                    for (Class c : parameterTypes) {
                        ParamDTO paramDTO = new ParamDTO();
                        paramDTO.setParamType(c.getName());
                        methodDTO.addParamList(paramDTO);
                    }
                }
            }
        }
        return resourceDTO;
    }


    /**
     * 执行方法
     * @param invokeVO
     * @return
     * @throws Exception
     */
    @Override
    public Object execute(InvokeVO invokeVO) throws Exception {
        Class clszz = Class.forName(invokeVO.getInterfaceName());
        CallRequest request = new CallRequest();
        request.setInterfaceClass(clszz);
        request.setVersion(invokeVO.getVersion());
        request.setModel(invokeVO.getModel());
        Method method = getMethod(clszz, invokeVO.getMethodName(), invokeVO.getParamType());
        Type[] parameterTypes = method.getGenericParameterTypes();

        List<Object> paramList = new ArrayList<>();
        if (ArrayUtils.isNotEmpty(parameterTypes)) {
            for (int i = 0; i < parameterTypes.length; i++) {
                paramList.add(constactParamete(parameterTypes[i], invokeVO.getParam().get(i)));
            }
        }

        request.setParam(paramList);
        logger.info("开始执行：{}", JsonMapper.nonEmptyMapper().toJson(request));
        return DubboCallUtil.call(request, method);
    }


}
